namespace SimpleWebServices.Configuration
{
    using System;
    using System.Collections.ObjectModel;
    using System.Xml;
    using System.Xml.Serialization;
    using System.Xml.XPath;
    using SimpleWebServices;
    using SimpleWebServices.Data;
    using Xunit;

    public sealed class RepositorySettingCollectionFacts
    {
        [Fact]
        public void typedef()
        {
            Assert.True(new ObjectExpectations<RepositorySettingCollection>()
                .DerivesFrom<Collection<RepositorySetting>>()
                .IsConcreteClass()
                .IsSealed()
                .HasDefaultConstructor()
                .XmlRoot("repositories")
                .Implements<IXmlSerializable>()
                .Result);
        }

        [Fact]
        public void deserialize()
        {
            RepositorySettingCollection actual = (
                "<repositories default='Default.Repository' urn='urn://example.com'>" +
                    "<repository key='Example1'>Example1.Repository</repository>" +
                    "<repository key='Example2'>Example2.Repository</repository>" +
                "</repositories>").Deserialize<RepositorySettingCollection>();

            Assert.Equal<string>("Default.Repository", actual.Default);
            Assert.Equal<string>("urn://example.com", actual.Urn);

            Assert.Equal<string>("Example1", actual[0].Key);
            Assert.Equal<string>("Example1.Repository", actual[0].Value);
            Assert.Equal<string>("Example2", actual[1].Key);
            Assert.Equal<string>("Example2.Repository", actual[1].Value);
        }

        [Fact]
        public void deserializeEmpty()
        {
            RepositorySettingCollection actual = "<repositories />".Deserialize<RepositorySettingCollection>();

            Assert.Null(actual.Default);
            Assert.Null(actual.Urn);
            Assert.Empty(actual);
        }

        [Fact]
        public void serialize()
        {
            RepositorySettingCollection obj = new RepositorySettingCollection
            {
                Default = "Default.Repository",
                Urn = "urn://example.com"
            };

            obj.Add("<repository key='Example1'>Example1.Repository</repository>".Deserialize<RepositorySetting>());
            obj.Add("<repository key='Example2'>Example2.Repository</repository>".Deserialize<RepositorySetting>());

            XPathNavigator navigator = obj.Serialize().CreateNavigator();

            Assert.True((bool)navigator.Evaluate("'Example1.Repository'=/repositories[@default='Default.Repository'][@urn='urn://example.com']/repository[@key='Example1']"));
            Assert.True((bool)navigator.Evaluate("'Example2.Repository'=/repositories[@default='Default.Repository'][@urn='urn://example.com']/repository[@key='Example2']"));
        }

        [Fact]
        public void ctor()
        {
            Assert.NotNull(new RepositorySettingCollection());
        }

        [Fact]
        public void prop_Default()
        {
            Assert.True(new PropertyExpectations(typeof(RepositorySettingCollection).GetProperty("Default"))
                .IsAutoProperty<string>()
                .Result);
        }

        [Fact]
        public void prop_Urn()
        {
            Assert.True(new PropertyExpectations(typeof(RepositorySettingCollection).GetProperty("Urn"))
                .IsAutoProperty<string>()
                .Result);
        }

        [Fact]
        public void prop_Indexer_string()
        {
            FakeRepository.Clear();

            try
            {
                RepositorySettingCollection obj = (
                    "<repositories>" +
                        "<repository key='Example'>Example.Repository</repository>" +
                    "</repositories>").Deserialize<RepositorySettingCollection>();

                FakeRepository.RegisterById("Example.Repository", "<repository><object><test /></object></repository>");

                IRepository repository = obj["Example"];

                Assert.True((bool)(repository as FakeRepository).Xml.CreateNavigator().Evaluate("1=count(/repository/object/test)"));
            }
            finally
            {
                FakeRepository.Reset();
            }
        }

        [Fact]
        public void prop_Indexer_stringNull_whenDefaultDefined()
        {
            FakeRepository.Clear();

            try
            {
                RepositorySettingCollection obj = "<repositories default='Default.Repository' />".Deserialize<RepositorySettingCollection>();

                FakeRepository.RegisterById("Default.Repository", "<repository><object><test /></object></repository>");

                IRepository repository = obj[null];

                Assert.True((bool)(repository as FakeRepository).Xml.CreateNavigator().Evaluate("1=count(/repository/object/test)"));
            }
            finally
            {
                FakeRepository.Reset();
            }
        }

        [Fact]
        public void prop_Indexer_stringEmpty_whenDefaultDefined()
        {
            FakeRepository.Clear();

            try
            {
                RepositorySettingCollection obj = "<repositories default='Default.Repository' />".Deserialize<RepositorySettingCollection>();

                FakeRepository.RegisterById("Default.Repository", "<repository><object><test /></object></repository>");

                IRepository repository = obj[string.Empty];

                Assert.True((bool)(repository as FakeRepository).Xml.CreateNavigator().Evaluate("1=count(/repository/object/test)"));
            }
            finally
            {
                FakeRepository.Reset();
            }
        }

        [Fact]
        public void prop_Indexer_stringUndefined_whenDefaultDefined()
        {
            FakeRepository.Clear();

            try
            {
                RepositorySettingCollection obj = "<repositories default='Default.Repository' />".Deserialize<RepositorySettingCollection>();

                FakeRepository.RegisterById("Default.Repository", "<repository><object><test /></object></repository>");

                IRepository repository = obj["Undefined"];

                Assert.True((bool)(repository as FakeRepository).Xml.CreateNavigator().Evaluate("1=count(/repository/object/test)"));
            }
            finally
            {
                FakeRepository.Reset();
            }
        }

        [Fact]
        public void prop_Indexer_stringNull()
        {
            FakeRepository.Clear();

            try
            {
                RepositorySettingCollection obj = "<repositories />".Deserialize<RepositorySettingCollection>();

                FakeRepository.Register("<repository><object><test /></object></repository>");

                IRepository repository = obj[null];

                Assert.True((bool)(repository as FakeRepository).Xml.CreateNavigator().Evaluate("1=count(/repository/object/test)"));
            }
            finally
            {
                FakeRepository.Reset();
            }
        }

        [Fact]
        public void op_Add_string_string()
        {
            RepositorySettingCollection obj = new RepositorySettingCollection();
            obj.Add("Example", "Example.Repository");

            Assert.Equal<string>("Example", obj[0].Key);
            Assert.Equal<string>("Example.Repository", obj[0].Value);
        }

        [Fact]
        public void op_Add_stringEmpty_string()
        {
            RepositorySettingCollection obj = new RepositorySettingCollection();
            obj.Add(string.Empty, "Example.Repository");

            Assert.Equal<string>(string.Empty, obj[0].Key);
            Assert.Equal<string>("Example.Repository", obj[0].Value);
        }

        [Fact]
        public void op_Add_stringNull_string()
        {
            RepositorySettingCollection obj = new RepositorySettingCollection();
            obj.Add(null as string, "Example.Repository");

            Assert.Null(obj[0].Key);
            Assert.Equal<string>("Example.Repository", obj[0].Value);
        }

        [Fact]
        public void op_Add_string_stringEmpty()
        {
            RepositorySettingCollection obj = new RepositorySettingCollection();
            obj.Add("Example", string.Empty);

            Assert.Equal<string>("Example", obj[0].Key);
            Assert.Equal<string>(string.Empty, obj[0].Value);
        }

        [Fact]
        public void op_Add_string_stringNull()
        {
            RepositorySettingCollection obj = new RepositorySettingCollection();
            obj.Add("Example", null as string);

            Assert.Equal<string>("Example", obj[0].Key);
            Assert.Null(obj[0].Value);
        }

        [Fact]
        public void IXmlSerializable_op_GetSchema()
        {
            Assert.Throws<NotSupportedException>(() => (new RepositorySettingCollection() as IXmlSerializable).GetSchema());
        }

        [Fact]
        public void IXmlSerializable_op_ReadXml_XmlReaderNull()
        {
            Assert.Throws<ArgumentNullException>(() => (new RepositorySettingCollection() as IXmlSerializable).ReadXml(null as XmlReader));
        }

        [Fact]
        public void IXmlSerializable_op_WriteXml_XmlWriterNull()
        {
            Assert.Throws<ArgumentNullException>(() => (new RepositorySettingCollection() as IXmlSerializable).WriteXml(null as XmlWriter));
        }
    }
}